#include <QWebFrame>
#include <QMessageBox>
#include <QString>
#include <QStringList>
#include <QWebSecurityOrigin>
#include <QLabel>
#include <QCalendarWidget>
#include "hybridpluginmanager.h"
#include "hybridplugininterface.h"
#include "coremethods.h"

#if defined(HAVE_QTSERVICEFRAMEWORK)
#include <QServiceManager.h>
#include <QServiceFilter.h>
QTM_USE_NAMESPACE
#endif

HybridPluginManager::HybridPluginManager(GraphicsHybridView *graphicsHybridView,
                                         QMainWindow *parentWindow,
                                         QString identifier) :
    m_hybridView(graphicsHybridView), 
    m_parentWindow(parentWindow),
    m_identifier(identifier)
{
    connect(graphicsHybridView->page(), SIGNAL(frameCreated(QWebFrame *)), this, SLOT(initFrame(QWebFrame *)));
}

QObject *HybridPluginManager::load(const QString &plugin)
{
#ifdef Q_OS_SYMBIAN
    QString pluginName = plugin + ".qtplugin";
#else
#ifdef Q_WS_MAEMO_5
    QString pluginName = "lib" + plugin + ".so";
#else
    QString pluginName = plugin + ".dll";
#endif
#endif

#ifdef Q_OS_WIN
    QString fullPluginName = pluginName;
#else
    QString pluginPath = QLibraryInfo::location(QLibraryInfo::PluginsPath);
#ifdef Q_WS_MAEMO_5
    QString fullPluginName = pluginPath + "/hybridplugins/" + pluginName;
#else
    QString fullPluginName = pluginPath + "\\hybridplugins\\" + pluginName;
#endif
#endif
    
    
    QPluginLoader loader(fullPluginName);

    m_errorString = "";

    if (!loader.load())
    {
#if defined(HAVE_QTSERVICEFRAMEWORK)
        QServiceManager manager;
        QObject *pluginInstance = manager.loadInterface(plugin);
        
        if(!pluginInstance)
        {
            qDebug() << "Error when loading plugin:" << plugin;
        }
        
        return pluginInstance;
#else
        m_errorString = loader.errorString();
        qDebug() << "Error when loading plugin" << loader.errorString() << fullPluginName;
        return 0;
#endif
    }

    QObject *pluginInstance = loader.instance();
    
    return pluginInstance;
}

QString HybridPluginManager::errorString()
{
    return m_errorString;
}

void HybridPluginManager::initFrame(QWebFrame *frame)
{
    qDebug() << "initFrame" << frame;
    if (frame)
    {
        CoreMethods *coreMethods = new CoreMethods(m_parentWindow,frame,this,m_identifier);
        connect(frame->page(), SIGNAL(windowCloseRequested()), this, SLOT(javaScriptWindowClose()));
        connect(frame, SIGNAL(loadFinished(bool)), SLOT(loadFinished(bool)));
        connect(frame, SIGNAL(javaScriptWindowObjectCleared()), SLOT(javaScriptWindowObjectCleared()));
        frame->addToJavaScriptWindowObject("hybrid", coreMethods);
        includeJavaScriptFile("hybridapi.js",frame);
    }
}

void HybridPluginManager::javaScriptWindowObjectCleared()
{
    // We received a signal that window object is cleared which means
    // our core methods object is deleted. Create it again. 
    initFrame(qobject_cast<QWebFrame *>(sender()));
}

void HybridPluginManager::includeJavaScriptFile(const QString &jsFileName, QWebFrame *frame)
{
    QUrl jsUrl = frame->url().resolved(QUrl(jsFileName));
    QFile file;

    if (frame->url().scheme() == "file")
        file.setFileName(jsUrl.toLocalFile());
    else if (frame->url().scheme() == "qrc")
        file.setFileName(":" + jsUrl.toString(QUrl::RemoveScheme));
    else
        return;
    
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << file.errorString();
        return;
    }
    
    QByteArray js = file.readAll();
    frame->evaluateJavaScript(QString(js));
    
    file.close();
}

void HybridPluginManager::includeCSSFile(const QString &cssFileName, QWebFrame *frame)
{
    QString includeScript = "\n\
        var hybridHead = document.getElementsByTagName(\"head\"); \n\
        var cssApplied; \n\
        if (hybridHead && !cssApplied) { \n\
            hybridHead = hybridHead[0]; \n\
            var hybridCSS = document.createElement('link'); \n\
            hybridCSS.type = 'text/css'; \n\
            hybridCSS.rel = 'stylesheet'; \n\
            hybridCSS.href = '" + cssFileName + "'; \n\
            hybridCSS.media = 'screen'; \n\
            hybridHead.appendChild(hybridCSS); \n\
            cssApplied = true; \n\
        }";
    qDebug() << "Evaluate:\n" << includeScript;
    frame->evaluateJavaScript(includeScript);
}

void HybridPluginManager::loadFinished(bool ok)
{
    if (ok)
    {
        includeCSSFile("disable-selection.css", qobject_cast<QWebFrame *>(sender()));
    }
}

void HybridPluginManager::javaScriptWindowClose()
{
    QCoreApplication::exit(0);
}
